package cn.com.generaldata.os.service.indicator_evaluation.development_index;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.Validate;
import org.nutz.castor.Castors;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.Record;
import org.nutz.dao.sql.Criteria;
import org.springframework.stereotype.Component;

import cn.com.generaldata.jsme_indicator_system.entity.IndicatorAccounting;
import cn.com.generaldata.jsme_indicator_system.entity.IndicatorEvaluation;
import cn.com.generaldata.jsme_indicator_system.util.Constants.IndicatorAccountingReferenceType;
import cn.com.generaldata.os.service.indicator_constant.ProvinceIndicatorConstant;
import cn.com.generaldata.os.service.indicator_evaluation.IndicatorEvaluationCalculateService;
import cn.com.generaldata.os.vo.IndicatorAccountVO;

@Component
public class TwoLevelEevelopmentIndexCalculateService extends IndicatorEvaluationCalculateService {

	private Map<String, Double> baseIndicatorValueMap;
	
	private List<Record> developmentIndexList;
	
	@Override
	protected Double calculate(IndicatorEvaluation indicator,
			IndicatorAccountVO indicatorAccountVO) {
		// TODO Auto-generated method stub

		if (developmentIndexList==null){
			developmentIndexList = initDevelopmentIndexInfo();
			baseIndicatorValueMap = getBaseIndicatorValue(indicatorAccountVO);
		}
		
		List<Record> threeLevelList = querySubDevelopmentIndexList(indicator);
		
		//如果是基期，直接返回基期对应的基数值
		if (indicatorAccountVO.getYear().intValue()==ProvinceIndicatorConstant.DEVELOPMENT_INDEX_BASE_PERIOD){
			return ProvinceIndicatorConstant.DEVELOPMENT_INDEX_BASE_RADICES;
		}
		
		Double weight = 0.0;
		Double vl = 0.0;
		
		if (indicatorAccountVO.getYear().intValue() > ProvinceIndicatorConstant.DEVELOPMENT_INDEX_BASE_PERIOD){
			for (Record rc : threeLevelList){
				Double threeLevelWeight = Castors.me().castTo(rc.get("di_weight"), Double.class);
				Double inputIndicatorValue = getCityInputIndicatorValue(rc.getString("DI_NAME"), indicatorAccountVO);
				Double baseIndicatorValue = baseIndicatorValueMap.get(rc.getString("DI_NAME"));
				int diType = rc.getInt("DI_TYPE");
				Double threeLevelValue = setWglh(baseIndicatorValue, inputIndicatorValue, diType);
				weight = weight + threeLevelWeight;
				
				vl = vl + threeLevelValue * threeLevelWeight;
			}
			return vl / weight;
		}
		
		return 0.0;
	}
	
	/**
	 * 对指标值进行无刚量化处理
	 * */
	private Double setWglh(Double baseIndicatorValue, Double inputIndicatorValue, int diType){
		
		if (ProvinceIndicatorConstant.DEVELOPMENT_INDEX_TYPE==diType){	//逆向指标
			
			return baseIndicatorValue / inputIndicatorValue * 100;
		}
		
		return inputIndicatorValue / baseIndicatorValue * 100;	//正向指标
	}
	
	
	/**
	 * 获取基期指标值
	 * */
	private Map<String, Double> getBaseIndicatorValue(IndicatorAccountVO indicatorAccountVO){
		Map<String, Double> baseMap = new HashMap<String, Double>();
		for (Record rc : developmentIndexList){
			indicatorAccountVO.setYear(ProvinceIndicatorConstant.DEVELOPMENT_INDEX_BASE_PERIOD);	//设置基期年份
			baseMap.put(rc.getString("DI_NAME"), getIndicatorValue(rc.getInt("INDICATOR_TYPE"), rc.getString("INDICATOR_NAME"), indicatorAccountVO));
		}
		
		return baseMap;
	}
	
	/**
	 * 获取发展指数基础指标相关值（核算指标、录入指标）
	 * */
	public Double getIndicatorValue(int indicatorType, String indicatorName, IndicatorAccountVO indicatorAccountVO){
		Double result = null;
		if (IndicatorAccountingReferenceType.ACCOUNTING.getValue()==indicatorType){
			result = getIndicatorAccountingValue(indicatorName, indicatorAccountVO, 1, 5, 7);	//获取省级核算相关指标值
		}else{
			result = getCityInputIndicatorValue(indicatorName, indicatorAccountVO);
		}
		return result;
	}

	private List<Record> initDevelopmentIndexInfo(){		
		List<Record> list = dao.query("t_indicator_di_info", null);
		return list;
	}
	
	
	private List<Record> querySubDevelopmentIndexList(IndicatorEvaluation indicator){
		
		List<Record> subList = new ArrayList<Record>();
		//查询发展指数Id
		int fid=0;
		for (Record rc : developmentIndexList){
			if (indicator.getName().equals(rc.getString("DI_NAME"))){
				fid = rc.getInt("ID");
			}
		}
		
		//根据父Id查询下级所有发展指数信息（三级发展指数）
		for (Record rc : developmentIndexList){
			if (rc.getInt("di_parent")==fid){
				subList.add(rc);
			}
		}
		
		return subList;
	}
	
	/**
	 * 获取录入指标对应的值
	 * 
	 * @param indicatorAccountVO
	 * @return
	 */
	private Double getCityInputIndicatorValue(String diName, IndicatorAccountVO indicatorAccountVO) {
		Integer indicatorId = getIndicatorInputId(diName, null);
		if (indicatorId==null){
			return null;
		}
		Criteria cri = getIndicatorDataCri(indicatorAccountVO, indicatorAccountVO.getYear(), indicatorId);
		Double result = getInputIndicatorValue(cri);
		Validate.isTrue(result != null);
		return result;
	}
	
	/**
	 * 获取指定年份核算指标值
	 * */
	private Double getIndicatorAccountingValue(String indicatorName, IndicatorAccountVO indicatorAccountVO, Integer... level){
		Double result = null;
		List<Record> recordList = getIndicatorAccount(indicatorName, indicatorAccountVO.getYear(), level);
		if (recordList!=null&&recordList.size()>0){
			result = Castors.me().castTo( recordList.get(0).get("edit_value"), Double.class);	//获取核算修正值
		}
		return result;
	}
	
	/**
	 * 获取核算指标值
	 * */
	public List<Record> getIndicatorAccount(String indicatorName, Integer year, Integer... level){
		Cnd cnd = Cnd.where("name", "=", indicatorName);
		if (level != null && level.length > 0) {
			cnd.and("section", "IN", level);
		}
		List<IndicatorAccounting> indicators = indicatorSystemDao.query(IndicatorAccounting.class, cnd);
		long[] ids = null;
		if (indicators!=null && indicators.size()>0){
			ids = new long[indicators.size()];
			int i = 0;
			for (IndicatorAccounting ia : indicators){				
				ids[i] = ia.getId().longValue();
				i++;
			}
		}
		Criteria cri = Cnd.cri();
		cri.where().andIn("indicator_id", ids);
		cri.where().and("area_id", "=", ProvinceIndicatorConstant.PROVICE_AREA_ID);
		
		if (year!=null){
			cri.where().and("year", "=", year);
		}
		
		cri.getOrderBy().asc("year");
		List<Record> list = dao.query("tbl_indicator_account", cri);

		return list;
	}
}
